import shutil
import urllib
from pathlib import Path

from flask import abort, jsonify, send_from_directory, request, send_file, make_response, url_for, current_app
from flask_restful import Resource, reqparse
from flask_simplelogin import login_required
import os

from openpyxl.reader.excel import load_workbook
from openpyxl.styles import Side, Border
from werkzeug.exceptions import NotFound

from project_name.models import accounts, db
from urllib.parse import urlparse, parse_qs, quote
from datetime import datetime
from project_name.base import Admin_DIR, User_DIR, source_file
import pandas as pd
import numpy as np

from project_name.utils import get_real_path, excel_default_column


class AddUserResource(Resource):
    def post(self):
        parser = reqparse.RequestParser()
        parser.add_argument('adminId', type=str, required=True, help='adminId is required')
        parser.add_argument('username', type=str, required=True, help='username is required')
        parser.add_argument('password', type=str, required=True, help='password is required')
        data = parser.parse_args()

        if accounts.query.filter_by(username=data["username"]).first():
            return jsonify({"code": 404, "message": "用户已存在", "data": ""})

        new_user = accounts(
            id=str(data["username"]),
            username=str(data["username"]),
            password=str(data["password"]),
            id_type=1,
            parent_account_id=str(data["adminId"])
        )
        print("new_user", new_user)
        db.session.add(new_user)
        db.session.commit()

        return jsonify({"code": 200, "message": "用户添加成功", "data": new_user.to_dict()})


class SearchResource(Resource):
    def post(self):
        parser = reqparse.RequestParser()
        parser.add_argument('username', type=str, required=True, help='username is required')
        data = parser.parse_args()

        if data['username'] == "":
            results = accounts.query.all()
            transformed_data = []
            for record in results:
                transformed_data.append({
                    "id": record.id,
                    "username": record.username,
                    "parentId": record.parent_account_id,
                    "createAt": record.created_at.strftime('%Y-%m-%d %H:%M:%S'),
                    "idType": record.id_type
                })
            return jsonify({"code": 200, "data": transformed_data})
        results = accounts.query.filter_by(parent_account_id=data['username']).all()
        transformed_data = []
        for record in results:
            transformed_data.append({
                "id": record.id,
                "time": record.time,
            })
        return jsonify({"code": 200, "data": transformed_data})


class DeleteImageResource(Resource):
    def post(self):
        parser = reqparse.RequestParser()
        parser.add_argument('imagePath', type=str, required=True, help='imagePath is required')
        parser.add_argument('username', type=str, required=True, help='username is required')
        data = parser.parse_args()

        try:
            parsed_url = urlparse(data['imagePath'])
            query_params = parse_qs(parsed_url.query)
            full_path = query_params.get('path')
            full_path = User_DIR + "/" + data["username"] + "/" + full_path[0]

            if not os.path.exists(full_path):
                return jsonify({"status": "error", "message": "文件不存在"}), 404

            os.remove(full_path)
            return jsonify({"status": "success", "message": "删除成功"})
        except Exception as e:
            return jsonify({"status": "error", "message": str(e)}), 500


class GetImageResource(Resource):
    def post(self):
        parser = reqparse.RequestParser()
        parser.add_argument('path', type=str, required=True, help='imagePath is required')
        data = parser.parse_args()

        try:
            # 安全构建路径
            base_dir = Path(User_DIR)
            image_path = ''
            for s in data['path'].split(','):
                image_path += s + os.path.sep

            # 防止路径遍历攻击
            full_path = (base_dir / image_path).resolve()
            if not full_path.is_relative_to(base_dir.resolve()):
                raise ValueError("非法路径访问")

            image_file_url = []

            for item in os.listdir(full_path):
                # 如果文件不是图片格式就不要
                if item.split('.')[-1] not in ['jpg', 'jpeg', 'png']:
                    continue
                item_path = os.path.join(current_app.config['resource_url'], "static", "User", image_path, item)
                full_image_path = os.path.join(full_path, item)
                if os.path.isfile(full_image_path):
                    image_file_url.append(item_path)

            return {
                "code": 200,
                "data": image_file_url,
                "message": "获取成功"
            }

        except NotFound as e:
            return jsonify({
                "code": 404,
                "message": str(e)
            })
        except Exception as e:
            return jsonify({
                "code": 400,
                "message": str(e)
            })


class GetUserFileListResource(Resource):
    def post(self):
        parser = reqparse.RequestParser()
        parser.add_argument('username', type=str, required=True, help='username is required')
        data = parser.parse_args()

        try:
            full_path = os.path.join(User_DIR, data['username'])

            if not os.path.exists(full_path):
                os.makedirs(full_path, exist_ok=True)

            if not os.path.exists(full_path):
                return jsonify({"error": "路径不存在"}), 404

            file_list = []
            for item in os.listdir(full_path):
                item_path = os.path.join(full_path, item)
                if os.path.isdir(item_path):
                    file_list.append({
                        "name": item,
                        "type": "directory",
                    })
                else:
                    file_list.append({
                        "name": item,
                        "type": item.split('.')[-1],
                    })

            return jsonify({"code": 200, "message": "获取文件夹成功", "data": file_list})
        except Exception as e:
            return jsonify({"code": 400, "error": str(e), "data": ""})


class GetFilesResource(Resource):
    def post(self):
        parser = reqparse.RequestParser()
        parser.add_argument('path', type=str, required=True, help='path is required')
        parser.add_argument('username', type=str, required=True, help='username is required')
        data = parser.parse_args()

        try:
            full_path = os.path.join(User_DIR, data['username'])
            target_path = os.path.join(full_path, data['path'])

            if not os.path.exists(target_path):
                return jsonify({"error": "路径不存在"}), 404

            items = os.listdir(target_path)
            files = []
            folders = []

            for item in items:
                item_path = os.path.join(target_path, item)
                is_folder = os.path.isdir(item_path)

                file_info = {
                    "name": item,
                    "type": "directory" if is_folder else item.split('.')[-1],
                }
                if is_folder:
                    folders.append(file_info)
                    files.append(file_info)
                else:
                    if file_info['type'] in ['jpg', 'jpeg', 'png']:
                        file_info[
                            'url'] = f"${current_app.config['resource_url']}/getFile?path={urllib.parse.quote(os.path.relpath(os.path.join(target_path, item), full_path))}&username={urllib.parse.quote(data['username'])}"
                    files.append(file_info)

            return jsonify({
                "folders": folders,
                "files": files
            })
        except Exception as e:
            return jsonify({"error": str(e)}), 500


class GetFileResource(Resource):
    def get(self):
        file_path = request.args.get('path')
        username = request.args.get('username')
        if not file_path or not username:
            return jsonify({"error": "路径参数缺失"}), 400

        full_path = os.path.join(User_DIR, username)
        file_path = os.path.join(full_path, file_path)

        if not os.path.exists(file_path):
            return jsonify({"error": "文件不存在"}), 404

        if not file_path.lower().endswith(('.jpg', '.jpeg', '.png')):
            return jsonify({"error": "文件不是图片"}), 400

        directory = os.path.dirname(file_path)
        filename = os.path.basename(file_path)

        response = send_from_directory(directory, filename, mimetype='image/jpeg')
        response.headers['Access-Control-Expose-Headers'] = 'X-Custom-Message, Y-Custom-Message'

        file_name = os.path.basename(directory)
        dir_name = os.path.dirname(directory)
        excel_file = os.path.join(dir_name, "report.xlsx")

        if os.path.exists(excel_file):
            df = pd.read_excel(excel_file)
            if '姓名_日期_门诊号_拼音' in df.columns and '检查诊断' in df.columns and '检查过程' in df.columns:
                result_row = df[df['姓名_日期_门诊号_拼音'] == file_name]
                if not result_row.empty:
                    diagnosis_result = result_row['检查诊断'].values[0].replace("\n", "").replace("\r", "")
                    check_result = result_row['检查过程'].values[0].replace("\n", "").replace("\r", "")
                    response.headers['X-Custom-Message'] = quote(diagnosis_result, safe='')
                    response.headers['Y-Custom-Message'] = quote(check_result, safe='')

        return response


class SaveAnnotationResource(Resource):
    def post(self):
        file_path = request.json['path']
        username = request.json['username']
        image_name = request.json['imageName']
        fields = request.json['fields']
        sys_path = get_real_path(file_path, ",")

        # 生成excel路径
        excel_name = file_path.split(",")[-1] + ".xlsx"
        excel_dir = os.path.join(current_app.static_folder, "User", username, sys_path)
        excel_path = os.path.join(excel_dir, excel_name)

        # 确保目录存在
        os.makedirs(excel_dir, exist_ok=True)

        # 如果excel不存在，就创建一个
        if not os.path.exists(excel_path):
            df = pd.DataFrame(columns=excel_default_column)
        else:
            df = pd.read_excel(excel_path)

        # 查找匹配的行
        mask = df['图片名称'] == image_name
        if mask.any():
            # 更新现有行 - 将每个字段的值设为True或1或其他适当的值
            df.loc[mask, excel_default_column[1:]] = 0  # 重置所有字段为0
            for field in fields:
                df.loc[mask, field] = 1  # 或者使用其他适当的值

        else:
            # 添加新行
            new_row = {'图片名称': image_name}
            # 初始化所有字段为0/False，然后设置指定的字段
            new_row.update({col: 0 for col in excel_default_column if col != '图片名称'})
            for field in fields:
                new_row[field] = 1  # 或者使用其他适当的值
            df = pd.concat([df, pd.DataFrame([new_row])], ignore_index=True)

        # 保存Excel
        df.to_excel(excel_path, index=False)

        return jsonify({"code": 200, "message": "保存成功"})


class SavePatientResource(Resource):
    def post(self):
        file_path = request.json['path']
        username = request.json['username']
        excel_name = request.json['excelName']
        diagnosis_result = request.json['diagnosisResult']
        sys_path = get_real_path(file_path, ",")

        # 生成excel路径
        excel_dir = os.path.join(current_app.static_folder, "User", username, sys_path)
        excel_path = os.path.join(excel_dir, excel_name)

        # 确保目录存在
        os.makedirs(excel_dir, exist_ok=True)
        df = pd.read_excel(excel_path)
        # 查找匹配的行
        mask = df['图片名称'] == "诊断结果"
        if mask.any():
            df[excel_default_column[1]] = df[excel_default_column[1]].astype(str)  # 先转换为字符串类型
            df.loc[mask, excel_default_column[1]] = diagnosis_result  # 再赋值
        else:
            # 添加新行
            new_row = {'图片名称': "诊断结果", "方向左侧": diagnosis_result}
            df = pd.concat([df, pd.DataFrame([new_row])], ignore_index=True)

        # 保存Excel
        df.to_excel(excel_path, index=False)

        return jsonify({"code": 200, "message": "保存成功"})


class SubmitAnnotationResource(Resource):
    def post(self):
        parser = reqparse.RequestParser()
        parser.add_argument('imagePath', type=str, required=True, help='imagePath is required')
        parser.add_argument('data', type=dict, required=True, help='data is required')
        data = parser.parse_args()

        try:
            parsed = urlparse(data["imagePath"])
            query = parsed.query
            parts = query.split('&')
            path = parts[0].split('=', 1)[1]
            username = parts[1].split('=')[1] if len(parts) > 1 else None

            Accounts = accounts.query.get(username)
            parent_account_id = Accounts.parent_account_id
            full_path = os.path.join(User_DIR, username, path)
            admin_path = os.path.join(Admin_DIR, parent_account_id, "report", path)

            target_dir_admin = os.path.dirname(admin_path)

            if not os.path.exists(target_dir_admin):
                os.makedirs(target_dir_admin)

            excel_path = os.path.splitext(full_path)[0] + ".xlsx"
            admin_path = os.path.splitext(admin_path)[0] + ".xlsx"

            if not os.path.exists(excel_path):
                shutil.copy2(source_file, excel_path)
                shutil.copy2(source_file, admin_path)

            wb = load_workbook(excel_path)
            ws = wb.active
            wb_1 = load_workbook(admin_path)
            ws_1 = wb_1.active

            next_row = ws.max_row + 1
            thin_border = Border(left=Side(style='thin'), right=Side(style='thin'), top=Side(style='thin'),
                                 bottom=Side(style='thin'))

            for index, row in enumerate(ws.iter_rows(min_row=1, max_col=ws.max_column, values_only=True)):
                if row[0] == os.path.basename(path):
                    next_row = index + 1
                    break

            ws.cell(row=next_row, column=1, value=os.path.basename(path)).border = thin_border
            ws_1.cell(row=next_row, column=1, value=os.path.basename(path)).border = thin_border

            col = 2
            for key in ['type', 'location', 'weather', 'time', 'season', 'device', 'two', 'one', 'data']:
                value = ','.join(data['data'][key]) if key in data['data'] else 0
                ws.cell(row=next_row, column=col, value=value).border = thin_border
                ws_1.cell(row=next_row, column=col, value=value).border = thin_border
                col += 1

            wb.save(excel_path)
            wb_1.save(admin_path)

            return jsonify({"status": "success", "message": "标注提交成功"})
        except Exception as e:
            return jsonify({"status": "error", "message": str(e)}), 500


class GetExcelDataResource(Resource):
    def post(self):
        parser = reqparse.RequestParser()
        parser.add_argument('path', type=str, required=True, help='path is required')
        parser.add_argument('username', type=str, required=True, help='username is required')
        data = parser.parse_args()

        try:
            full_path = os.path.join(current_app.static_folder, "User", data['username'], data['path'])

            if not os.path.exists(full_path):
                return jsonify({'error': '文件不存在'}), 404

<<<<<<< HEAD
                # 直接构造最终字典结构
                d_result = image_feature_map.get("diagnosisResult")
                isMark = False if len(d_result) == 0 else True
                patient_info = {
                    'name': dir_name.name,
                    'isMark': isMark,
                    'images': image_file_list,
                    'diagnosisResult': d_result,
                    'checkingProcess': diagnosis.get(dir_name.name).get("checkingProcess"),
                    'diagnosis': diagnosis.get(dir_name.name).get("diagnosis")
                }
                patient_info_list.append(patient_info)
=======
            df = pd.read_excel(full_path)
>>>>>>> parent of d3b39cf (增加每保存一次都读取一次excel文件，保持客户端和服务端的患者、图片数据同步)

            data = {
                'headers': list(df.columns),
                'rows': df.values.tolist()
            }

            for row in data['rows']:
                for i in range(len(row)):
                    if isinstance(row[i], float) and np.isnan(row[i]):
                        row[i] = None
                    elif row[i] == 'nan':
                        row[i] = None
                    elif row[i] == 'None' or row[i] == 'null':
                        row[i] = None

            return jsonify({"code": 200, "message": "获取Excel数据成功", "data": data})
        except Exception as e:
            return jsonify({"code": 400, 'message': str(e)})
